"""
Interface graphique.
Utilise Qt.
"""

from PyQt4 import Qt
from PyQt4 import QtGui
from PyQt4 import QtOpenGL
from PyQt4 import QtCore
from OpenGL.GL import *
from OpenGL.GLU import *

class MyWindow(QtGui.QMainWindow):
    ''' Fenetre principale. '''
    
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
	self.resize(800, 600)
        
        # defini un widget opengl
        #widget = QtGui.QPushButton('blou')
        #self.setCentralWidget(widget)
	self.widget = drawer(self)
	self.setCentralWidget(self.widget)
        # menu
        self.menuBar = QtGui.QMenuBar(self)
        # fichier
        self.menuFichier = QtGui.QMenu("&Fichier")
        self.menuBar.addMenu(self.menuFichier)
	actionOuvrir = self.menuFichier.addAction("&Ouvrir fichier raw")
        actionOuvrir.setShortcut("Ctrl+O")
	self.connect(actionOuvrir, Qt.SIGNAL("activated()"), Qt.SLOT("open()"))
        actionQuitter = self.menuFichier.addAction("&Quitter")
        actionQuitter.setShortcut("Ctrl+Q")
        self.connect(actionQuitter, Qt.SIGNAL("activated()"), Qt.SLOT("close()"))
	# Aide / ?
	#self.menuAPropos = QtGui.QMenu("&?")
        #self.menuBar.addMenu(self.menuAPropos)
        # enregistre le menu
        self.setMenuBar(self.menuBar)

    def keyPressEvent(self, event):
	self.widget.keyPressEvent(event)

    @QtCore.pyqtSlot()
    def open(self):
	fileName = QtGui.QFileDialog.getOpenFileName(self, "Ouvrir fichier raw", "/home/", "Raw Files (*.raw)")
	self.widget.loadModel(createtriangles(fileName))
  

class MyApp(QtGui.QApplication):
    ''' Application '''
    
    def __init__(self):
        QtGui.QApplication.__init__(self, ['iutpython3d'])
        self.window = MyWindow()
        
    def executer(self):
        """ Lance l'application. """
        self.window.show()
        self.exec_()

class drawer(QtOpenGL.QGLWidget):
    def __init__(self, parent):
	QtOpenGL.QGLWidget.__init__(self, parent)
	self.trianglelist= []
	self.rotatex= 0.0
	self.rotatey= 0.0
	self.rotatez= 0.0
	self.click= 0
	self.mousex= 0.0
	self.mousey= 0.0
	self.LightPos= [2,0,5,1]
	self.zoom= 5

    def initializeGL(self):
        glEnable(GL_DEPTH_TEST)
	glEnable(GL_LIGHTING)  	
  	glEnable(GL_LIGHT0)
	glEnable(GL_NORMALIZE)
        
    def resizeGL(self, w, h):
        glViewport(0, 0, w, h)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(90.0, float(w)/float(h), 0.1, 500.0)       

    def paintGL(self):
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
	glLightiv(GL_LIGHT0, GL_POSITION, self.LightPos);
	gluLookAt(0.0, 0.0, self.zoom, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)        
	glRotatef(self.rotatex, 1.0, 0.0, 0.0)
	glRotatef(self.rotatey, 0.0, 1.0, 0.0)
	glShadeModel(GL_SMOOTH)
	glBegin(GL_TRIANGLES)
    	glColor3f(1.0, 1.0, 1.0)
	for trianglea in self.trianglelist:
		glNormal3f(trianglea.normal.x, trianglea.normal.y, trianglea.normal.z)
		glVertex3f(trianglea.point1.x, trianglea.point1.y, trianglea.point1.z)
		glVertex3f(trianglea.point2.x, trianglea.point2.y, trianglea.point2.z)
		glVertex3f(trianglea.point3.x, trianglea.point3.y, trianglea.point3.z)
        glEnd()
	
    def keyPressEvent(self, event):
	if event.key() == QtCore.Qt.Key_Up:
		self.rotatex += 5.0
	if event.key() == QtCore.Qt.Key_Down:
		self.rotatex -= 5.0
	if event.key() == QtCore.Qt.Key_Left:
		self.rotatey -= 5.0
	if event.key() == QtCore.Qt.Key_Right:
		self.rotatey += 5.0
	self.updateGL()

    def mousePressEvent(self, event):
	if event.button() == QtCore.Qt.LeftButton:
		self.click = 1
		self.mousex= event.x()
		self.mousey= event.y()   		
	
    def mouseReleaseEvent(self, event):
	if event.button() == QtCore.Qt.LeftButton:
		self.click = 0
    
    def mouseMoveEvent(self, event):
	if self.click :
		x= event.x()-self.mousex
		y= event.y()-self.mousey
		self.rotatex+= y
		self.rotatey+= x
		self.mousex= event.x()
		self.mousey= event.y()	
		self.updateGL()

    def wheelEvent(self, event):
	if event.delta()>0:
		if self.zoom>0.0:
			self.zoom-= 0.2
	if event.delta()<0:
		self.zoom+= 0.2
	self.updateGL()
    def loadModel(self, trianglelist):
	self.trianglelist= trianglelist
	self.updateGL

# Calcule le produit vectoriel
def cross(pointa, pointb):
	return point(pointa.y*pointb.z-pointa.z*pointb.y, pointa.z*pointb.x-pointa.x*pointb.z, pointa.x*pointb.y-pointa.y*pointb.x)

# Construit la liste des triangles a partir d'un fichier raw
def createtriangles(filename):
	trianglelist= []
	try:
		fichier= open(filename, "r")
		while(1):
			line= fichier.readline()
			if line== '':
				break;
			pointslist= line.split(' ')
			pointslist.pop() # Removes last item in the list ('\n')
			if len(pointslist) != 9:
				print "Fichier raw non conforme"
				break;
			point1= point(float(pointslist[0]), float(pointslist[1]), float(pointslist[2]))
			point2= point(float(pointslist[3]), float(pointslist[4]), float(pointslist[5]))
			point3= point(float(pointslist[6]), float(pointslist[7]), float(pointslist[8]))
			pointa= point(point2.x-point1.x, point2.y-point1.y, point2.z-point1.z)
			pointb= point(point3.x-point1.x, point3.y-point1.y, point3.z-point1.z)
			normal= cross(pointa, pointb)
			trianglea= triangle(point1, point2, point3, normal)
			trianglelist.append(trianglea)
	except IOError, err:
		print "Le fichier", filename, "est introuvable."
	return trianglelist


# On definit les classes qui nous seront utiles par la suite
class point:
	def __init__(self, x, y, z):
		self.x= x
		self.y= y
		self.z= z
class triangle:
	def __init__(self, point1, point2, point3, normal):
		self.point1= point1
		self.point2= point2
		self.point3= point3
		self.normal= normal

